#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_TREE_HT 100

// 哈夫曼树节点
typedef struct MinHeapNode {
    char data;
    float freq;
    struct MinHeapNode* left;
    struct MinHeapNode* right;
} MinHeapNode;

// 哈夫曼树
typedef struct MinHeap {
    unsigned size;
    unsigned capacity;
    struct MinHeapNode** array;
} MinHeap;

// 创建一个新的哈夫曼树节点，添加错误处理
MinHeapNode* newNode(char data, float freq) {
    MinHeapNode* temp = (MinHeapNode*)malloc(sizeof(MinHeapNode));
    if (temp == NULL) {
        return NULL;
    }
    temp->left = temp->right = NULL;
    temp->data = data;
    temp->freq = freq;
    return temp;
}

// 创建一个哈夫曼树，添加内存分配失败的错误处理
MinHeap* createMinHeap(unsigned capacity) {
    MinHeap* minHeap = (MinHeap*)malloc(sizeof(MinHeap));
    if (minHeap == NULL) {
        return NULL;
    }
    minHeap->size = 0;
    minHeap->capacity = capacity;
    minHeap->array = (MinHeapNode**)malloc(minHeap->capacity * sizeof(MinHeapNode*));
    if (minHeap->array == NULL) {
        free(minHeap);
        return NULL;
    }
    return minHeap;
}

// 交换两个哈夫曼树节点
void swapMinHeapNode(MinHeapNode** a, MinHeapNode** b) {
    MinHeapNode* t = *a;
    *a = *b;
    *b = t;
}

// 最小堆化
void minHeapify(MinHeap* minHeap, int idx) {
    int smallest = idx;
    int left = 2 * idx + 1;
    int right = 2 * idx + 2;

    if (left < minHeap->size && minHeap->array[left]->freq < minHeap->array[smallest]->freq)
        smallest = left;

    if (right < minHeap->size && minHeap->array[right]->freq < minHeap->array[smallest]->freq)
        smallest = right;

    if (smallest != idx) {
        swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);
        minHeapify(minHeap, smallest);
    }
}

// 检查大小是否为1
int isSizeOne(MinHeap* minHeap) {
    return (minHeap->size == 1);
}

// 提取最小值节点
MinHeapNode* extractMin(MinHeap* minHeap) {
    MinHeapNode* temp = minHeap->array[0];
    minHeap->array[0] = minHeap->array[minHeap->size - 1];
    --minHeap->size;
    minHeapify(minHeap, 0);
    return temp;
}

// 插入一个新节点
void insertMinHeap(MinHeap* minHeap, MinHeapNode* minHeapNode) {
    ++minHeap->size;
    int i = minHeap->size - 1;
    while (i && minHeapNode->freq < minHeap->array[(i - 1) / 2]->freq) {
        minHeap->array[i] = minHeap->array[(i - 1) / 2];
        i = (i - 1) / 2;
    }
    minHeap->array[i] = minHeapNode;
}

// 构建哈夫曼树
MinHeapNode* buildHuffmanTree(char data[], float freq[], int size) {
    MinHeapNode* left, * right, * top;
    MinHeap* minHeap = createMinHeap(size);
    if (minHeap == NULL) {
        return NULL;
    }
    for (int i = 0; i < size; ++i) {
        minHeap->array[i] = newNode(data[i], freq[i]);
        if (minHeap->array[i] == NULL) {
            // 若创建节点失败，释放已分配的资源并返回NULL
            for (int j = 0; j < i; j++) {
                free(minHeap->array[j]);
            }
            free(minHeap->array);
            return NULL;
        }
    }
    minHeap->size = size;
    int i;
    for (i = (minHeap->size - 1) / 2; i >= 0; --i) {
        minHeapify(minHeap, i);
    }
    while (!isSizeOne(minHeap)) {
        left = extractMin(minHeap);
        right = extractMin(minHeap);
        top = newNode('$', left->freq + right->freq);
        if (top == NULL) {
            // 若创建新合并节点失败，释放相关资源并返回NULL
            free(left);
            free(right);
            for (int j = 0; j < minHeap->size; j++) {
                free(minHeap->array[j]);
            }
            free(minHeap->array);
            free(minHeap);
            return NULL;
        }
        top->left = left;
        top->right = right;
        insertMinHeap(minHeap, top);
    }
    return extractMin(minHeap);
}

// 打印哈夫曼编码
void printCodes(MinHeapNode* root, int arr[], int top) {
    if (root->left) {
        arr[top] = 0;
        printCodes(root->left, arr, top + 1);
    }
    if (root->right) {
        arr[top] = 1;
        printCodes(root->right, arr, top + 1);
    }
    if (!(root->left) && !(root->right)) {
        printf("%c: ", root->data);
        for (int i = 0; i < top; ++i)
            printf("%d", arr[i]);
        printf("\n");
    }
}

// 译码
void decode(MinHeapNode* root, const char* encodedText) {
    if (root == NULL || encodedText == NULL) {
        printf("输入非英文字母，无法译码\n");
        return;
    }
    MinHeapNode* curr = root;
    for (int i = 0; encodedText[i] != '\0'; i++) {
        if (encodedText[i] == '0')
            curr = curr->left;
        else
            curr = curr->right;

        // 如果到达叶子节点
        if (!(curr->left) && !(curr->right)) {
            printf("%c", curr->data);
            curr = root;
        }
    }
    printf("\n");
}

void encode(MinHeapNode* root, char x,int arr[],int top) {
    if (root->left) {
        arr[top] = 0;
        encode(root->left,x, arr, top + 1);
    }
    if (root->right) {
        arr[top] = 1;
        encode(root->right,x, arr, top + 1);
    }
    if (!(root->left) && !(root->right)&& root->data==x) {
        for (int i = 0; i < top; ++i)
            printf("%d", arr[i]);
    }
}

// 打印哈夫曼树
void printTree(MinHeapNode* root) {
    if (root != NULL) {
        if (root->data != '$') {
            printf("%c ", root->data);
        }
        printTree(root->left);
        printTree(root->right);
    }
}

// 释放哈夫曼树内存，采用后序遍历的方式正确释放节点内存
void freeTree(MinHeapNode* root) {
    if (root == NULL) {
        return;
    }
    freeTree(root->left);
freeTree(root->right);
free(root);
}

// 主函数
int main() {
    char data[] = { ' ','E','T','O','A','N','I','R','S','H','D','L','C','U','F','M','P','Y','W','G','B','V','K','X','J','Q','Z' };
    float freq[] = { 0.2,0.105,0.071,0.0644,0.063,0.059,0.054,0.053,0.052,0.047,0.035,0.029,0.023,0.0225,0.0221,0.021,0.0175,0.012,0.012,0.011,0.0105,0.008,0.003,0.002,0.001,0.001,0.001 };
    int size = sizeof(data) / sizeof(data[0]);
    MinHeapNode* root = buildHuffmanTree(data, freq, size);
    if (root == NULL) {
        printf("哈夫曼树构建失败，程序退出\n");
        return 1;
    }
    int arr[MAX_TREE_HT], top = 0;

    // 假设电报内容为 "HELLO WORLD"
    char encodedText[] = "1111001010010100101011001110111101101101001011010"; // 假设这是编码后的文本
    printf("翻译结果为: ");
    decode(root, encodedText); // 进行译码

    char decodedText[] = "SEE YOU AGAIN";
    int length = sizeof(decodedText) / sizeof(decodedText[0]);
    if (root == NULL || decodedText == NULL) {
        printf("输入参数不合法，无法编码\n");
        return;
    }
    for (int i = 0; i < length; i++){
        encode(root, decodedText[i], arr, top);
    }
    printf("\n");

    printTree(root); // 打印哈夫曼树
    printf("\n");

    printCodes(root, arr, top); // 打印编码

    freeTree(root);

    return 0;
}